%{
#include <stdio.h>
#include <math.h>

%}

%union {
  char* val;
}

%token <val> INT STATIC VOID
%token OU ET
%token EGAL DIF INF_EG SUP_EG
%token IF WHILE ELSE RETURN EXIT READ
%token <val> ID ENTIER
%token END 0 "end of file"

%nonassoc EGAL DIF INF_EG SUP_EG '<' '>' 
%nonassoc INT VOID STATIC ID ENTIER
%nonassoc IF WHILE ELSE RETURN EXIT READ

%left ','
%left ';'
%left OU
%left ET
%left '+' '-'
%left '*' '/' '%'
%left '[' ']'
%left '(' ')'
%left '{' '}'

%right '='
%right '!'

%error-verbose

%%


prog : //l_declarations l_fonctions 
  declarations en_tete l_instructions
;

l_declarations : /* Empty */
  | declarations ';' l_declarations
//	       | declarations l_declarations
;

declarations : INT ID
             | INT ID '[' ENTIER ']'
             | STATIC INT ID
             | STATIC INT ID '[' ENTIER ']'
	     | prototype
;
 

prototype : INT ID '(' suite_types ')'
          | VOID ID '(' suite_types ')'
;

/* type : VOID  */
/*      | INT */
/* ; */

suite_types : VOID
            | liste_types
;

liste_types : INT
            | INT ',' liste_types
;

/* l_fonctions : fonction */
/*             | fonction l_fonctions */
/* ; */

/* fonction : en_tete '{' corps '}' */
/* ; */

en_tete: VOID ID '(' s_param ')' 
       | INT ID '(' s_param ')'
;

s_param : VOID
        | l_param
;

l_param : param
        | param ',' l_param
;

param : INT ID
      | INT ID '[' ENTIER ']'
;

/* corps : //l_declarations l_instructions */
/* declarations l_instructions */
/* ; */

l_instructions : /* Empty */
               | instruction l_instructions
               | IF '(' exp ')' l_instructions l_instructions
;

//ya un probleme la apparament cf y.output
instruction : ID '=' exp';'
            | ID '[' exp ']=' exp';'
            | EXIT '(' ENTIER ')' ';'
            | RETURN exp';'
            | RETURN';'
            | READ '(' ID ')' ';'
            | IF '(' exp ')' instruction ELSE instruction
            | WHILE '(' exp ')' instruction
            | '{' l_instructions '}'
            | exp';'
;

exp : exp '+' exp
    | exp '-' exp
    | exp '*' exp
    | exp '/' exp
    | exp '%' exp
    | exp '=' exp
    | exp '<' exp
    | exp '>' exp
    | exp INF_EG exp
    | exp SUP_EG exp
    | exp DIF exp
    | exp EGAL exp
    | exp ET exp
    | exp OU exp
    | '-' exp
    | '!' exp
    | '(' exp ')'
    | ID
    | ID '('liste_argum  ')'
    | ID '[' exp ']'
    | ENTIER
;

liste_argum : exp
        | exp ',' liste_argum
        |  /* Empty */
;


%%

yyerror(char *message)
{
  printf("%s\n", message);
}

int main(int argc, char *argv[])
{
  if(yyparse() == 0)
    printf("Programme lexicalement et syntaxiquement correct\n");
  return(0);
}
 
